﻿using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using VOICeVIO.Hybrid.DB;
using VOICeVIO.Hybrid.Models;

namespace VOICeVIO.Hybrid.Services
{
    public class HybridService
    {
        private readonly HybridDbContext _hybridDb;

        public HybridService(HybridDbContext hybridDb)
        {
            this._hybridDb = hybridDb;
        }

        public async Task InsertSongAsync(SongDetailModel song)
        {
            var entity = new Song()
            {
                Uid = song.Uid,
                SongName = song.SongName,
                Author = song.Author,
                Note = song.Note,
                CreateTime = DateTime.Now,
                Link = song.Link,
                IsPublic = song.IsPublic,
                ProjectHash = song.ProjectHash,
                IP = song.IP,
                Singer = song.Singer,
                Volume = song.Volume
            };

            _hybridDb.Songs.Add(entity);
            await _hybridDb.SaveChangesAsync();
        }

        public async Task DeleteSongAsync(string uid)
        {
            var song = await _hybridDb.Songs.FirstOrDefaultAsync(s => s.Uid == uid);
            if (song == null)
            {
                return;
            }

            _hybridDb.Remove(song);
            await _hybridDb.SaveChangesAsync();
        }

        public async Task<int> GetUploadCountAsync(string Ip, bool today = true)
        {
            if (!today)
            {
                return await _hybridDb.Songs.CountAsync(s => s.IP == Ip);
            }
            return await _hybridDb.Songs.CountAsync(s => s.IP == Ip && s.CreateTime.Date == DateTime.UtcNow.Date);
        }

        public async Task<SongEditModel> GetSongByUidAsync(string uid)
        {
            var song = await _hybridDb.Songs.FirstOrDefaultAsync(s => s.Uid == uid);
            if (song == null)
            {
                return null;
            }

            return new SongEditModel
            {
                Uid = song.Uid,
                Author = song.Author,
                CreateTime = song.CreateTime,
                Note = song.Note,
                IsPublic = song.IsPublic,
                SongName = song.SongName,
                Singer = song.Singer,
                Volume = song.Volume
            };
        }

        public async Task UpdateSongAsync(SongEditModel model)
        {
            var song = await _hybridDb.Songs.FirstOrDefaultAsync(s => s.Uid == model.Uid);
            if (song == null)
            {
                return;
            }

            song.SongName = model.SongName;
            song.Author = model.Author;
            song.IsPublic = model.IsPublic;
            song.Note = model.Note;

            _hybridDb.Songs.Update(song);
            await _hybridDb.SaveChangesAsync();
        }

        public async Task<SongDetailModel> GetSongByHashAsync(string hash)
        {
            var song = await _hybridDb.Songs.FirstOrDefaultAsync(s => s.ProjectHash == hash);
            if (song == null)
            {
                return null;
            }

            return new SongDetailModel() { Author = song.Author, CreateTime = song.CreateTime, IsPublic = song.IsPublic };
        }

        public async Task<SongDetailModel> GetSongByIdAsync(int id, bool onlyPublic = false)
        {
            var song = await _hybridDb.Songs.FirstOrDefaultAsync(s => s.Id == id);
            if (song == null)
            {
                return null;
            }

            if (!song.IsPublic && onlyPublic)
            {
                return null;
            }

            return new SongDetailModel
            {
                Author = song.Author,
                CreateTime = song.CreateTime,
                Note = song.Note,
                IsPublic = song.IsPublic,
                SongName = song.SongName
            };
        }

        public async Task<List<SongListModel>> GetAllPublicSongsAsync()
        {
            return await _hybridDb.Songs.Where(s => s.IsPublic).Select(m => new SongListModel()
            {
                Author = m.Author,
                Id = m.Id,
                SongName = m.SongName
            }).ToListAsync();
        }

        public async Task<List<SongListModel>> SearchSongsAsync(string uid)
        {
            return await _hybridDb.Songs.Where(s => s.Uid == uid).Select(m => new SongListModel()
            {
                Author = m.Author,
                Id = m.Id,
                Uid = m.Uid,
                SongName = m.SongName
            }).ToListAsync();
        }

    }
}
